package ee.propaganda.gparrot.client.model;

import java.util.Vector;
import java.util.HashMap;

import com.google.gwt.user.client.rpc.AsyncCallback;

import ee.propaganda.gparrot.client.app.AppServices;
import ee.propaganda.gparrot.client.event.ServicesDataUpdatedEvent;
import ee.propaganda.gparrot.client.model.ServiceInfo.ServiceType;

public class Data {
	//singleton instance of itself
	private static Data data;
	
	//data variable
	
	private Vector<ServiceInfo> registeredServices;
	
	//app services
	private AppServices appServices = AppServices.getInstance();
	
	//constructor
	private Data(){
		
		
	}
	
	public void init(){
		getRegisteredServices();
	}
	
	public static Data getInstance() {
		if (data == null)
			data = new Data();
		return data;
	}

	public void updateAll() {
		appServices.getDataService().updateAll(appServices.getLoginInfo(), registeredServices, new AsyncCallback<Void>(){

			@Override
			public void onFailure(Throwable caught) {
				appServices.handleError(caught);
			}

			@Override
			public void onSuccess(Void result) {
				appServices.getEventBus().fireEvent(new ServicesDataUpdatedEvent());
			}
			
			
		});
		
	}

	public boolean isRegistered(ServiceType st){
		boolean isRegistered = false;
		String accessToken = null;
		ServiceInfo serviceInfo = getServiceByType(st);
		if (serviceInfo != null)
			accessToken = serviceInfo.getAccessToken();
		if (accessToken != null && accessToken != "") 
			isRegistered = true;
		return isRegistered;
	}
	
	public HashMap<ServiceType, Boolean> getServicesData() {
		HashMap<ServiceType, Boolean> servicesData = new HashMap<ServiceType, Boolean>();
		for (ServiceType st : ServiceType.values()) {
			//add registered status to hashmap	
			servicesData.put(st, isRegistered(st));
		}
		return servicesData;
	}
	
	public void update(ServiceType st, String accessToken) {
		ServiceInfo si = new ServiceInfo();
		si.setServiceType(st);
		si.setAccessToken(accessToken);
		appServices.getDataService().update(appServices.getLoginInfo(), si, new AsyncCallback<Vector<ServiceInfo>>() {

			@Override
			public void onFailure(Throwable caught) {
				appServices.handleError(caught);
				
			}

			@Override
			public void onSuccess(Vector<ServiceInfo> result) {
				setRegisteredServices(result);
				appServices.getEventBus().fireEvent(new ServicesDataUpdatedEvent());
			}
		});
	}

	//-----------------------------------------
	//Helper methods
	private void setRegisteredServices(Vector<ServiceInfo> registeredServices) {
		this.registeredServices = registeredServices;
	}
	
	
	//Returns the local collection of data about services. The method
	//assumes that local data is always up to date. Only if the information
	//is not initialised, the method retrieves the data from the server.
	private Vector<ServiceInfo> getRegisteredServices() {
		//if collection of services is not initialised, retrieve the data from server
		if (registeredServices == null){
			appServices.getDataService().getServices(appServices.getLoginInfo(), new AsyncCallback<Vector<ServiceInfo>>() {
				
				@Override
				public void onSuccess(Vector<ServiceInfo> result) {
					setRegisteredServices(result);
					appServices.getEventBus().fireEvent(new ServicesDataUpdatedEvent());
				}
				
				@Override
				public void onFailure(Throwable caught) {
					appServices.handleError(caught);
				}
			});
		}
		
		return registeredServices;
	}
	
	private ServiceInfo getServiceByType(ServiceInfo.ServiceType serviceType){
		Vector<ServiceInfo> services = getRegisteredServices();
		if(services == null){
			return null;
		}
		ServiceInfo service = null;
		while (services.iterator().hasNext() && service == null){
			ServiceInfo test = services.iterator().next();
			if (test.getServiceType() == serviceType)
				service = test;
		}
		return service;
	}

	
}
